﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ControlLibary
{
    /// <summary>
    ///  可分组的列 (该列必须是 Grid 的第一列) 
    /// </summary>
    public class GroupColumn : DataGridViewColumn
    {
        public GroupColumn() : base(new GroupCell())
        {
            ReadOnly = true;
        }

        public override DataGridViewCell CellTemplate
        {
            get
            {
                return base.CellTemplate;
            }
            set
            {
                if ((value != null) && !(value is GroupCell))
                {
                    throw new InvalidCastException("Need System.Windows.Forms.DataGridViewGroupCell");
                }
                base.CellTemplate = value;
            }
        }
    }

    public class GroupCell : DataGridViewTextBoxCell
    {

        public bool InRect = false;
        #region Variant

        /// <summary>
        /// 标示的宽度
        /// </summary>
        const int PLUS_WIDTH = 24;

        /// <summary>
        /// 标示的区域
        /// </summary>
        Rectangle groupPlusRect;

        int LastChild = -1;

        #endregion

        #region Init

        public GroupCell()
        {
            groupLevel = 1;
        }

        #endregion

        #region Property

        int groupLevel;

        /// <summary>
        /// 组级别(以1开始)
        /// </summary>
        public int GroupLevel
        {
            get { return groupLevel; }
            set { groupLevel = value; }
        }

        GroupCell parentCell;

        /// <summary>
        /// 父节点
        /// </summary>
        public GroupCell ParentCell
        {
            get
            {
                return parentCell;
            }
            set
            {
                if (value == null)
                    throw new NullReferenceException("父节点不可为空");
                if (!(value is GroupCell))
                    throw new ArgumentException("父节点必须为 DataGridViewGroupCell 类型");

                parentCell = value;
                parentCell.AddChildCell(this);
            }
        }

        private bool collapsed;

        /// <summary>
        /// 是否收起
        /// </summary>
        public bool Collapsed
        {
            get { return collapsed; }
        }

        private List<GroupCell> childCells = null;

        /// <summary>
        /// 所有的子结点
        /// </summary>
        public GroupCell[] ChildCells
        {
            get
            {
                if (childCells == null)
                    return null;
                return childCells.ToArray();
            }
        }

        /// <summary>
        /// 取得组标示(有+或-号的框)的区域
        /// </summary>
        public Rectangle GroupPlusRect
        {
            get
            {
                return groupPlusRect;
            }
        }

        bool bPaint = true;

        /// <summary>
        /// 是否重绘
        /// </summary>
        public bool BPaint
        {
            get { return bPaint; }
            set { bPaint = value; }
        }

        #endregion

        #region 添加子节点

        /// <summary>
        /// 添加子结点
        /// </summary>
        /// <param name="cell"></param>
        /// <returns></returns>
        public int AddChildCell(GroupCell cell)
        {
            return AddChildCellRange(new GroupCell[] { cell });
        }

        public int AddChildCellRange(GroupCell[] cells)
        {
            bool needRedraw = false;
            if (childCells == null)
            {
                //需要画一个加号
                childCells = new List<GroupCell>();
                needRedraw = true;
            }
            foreach (GroupCell cell in cells)
            {
                childCells.Add(cell);
                cell.groupLevel = groupLevel + 1;
                cell.parentCell = this;
                if (cell.RowIndex >= LastChild)
                {
                    LastChild = cell.RowIndex;
                }
            }

            if (needRedraw)
                DataGridView.InvalidateCell(this);
            return childCells.Count;
        }

        public int AddChildCell(int cellRowIndex)
        {
            return AddChildCellRange(new int[] { cellRowIndex });
        }

        public int AddChildCellRange(int[] cellsRowIndex, bool expand = true, bool needredraw = true)
        {
            bool needRedraw = false;
            if (childCells == null)
            {
                //需要画一个加号
                childCells = new List<GroupCell>();
                needRedraw = needredraw;
                this.collapsed = !expand;
            }

            foreach (int rowindex in cellsRowIndex)
            {
                GroupCell cell = this.DataGridView.Rows[rowindex].Cells[this.ColumnIndex] as GroupCell;
                childCells.Add(cell);
                cell.groupLevel = groupLevel + 1;
                cell.parentCell = this;

                if (rowindex >= LastChild)
                {
                    LastChild = rowindex;
                }

                if (cell.ChildCells != null)
                {
                    foreach (GroupCell _cell in cell.ChildCells)
                    {
                        _cell.groupLevel = cell.groupLevel + 1;
                    }
                }
                //this.DataGridView.Rows[rowindex].Visible = expand;
            }

            if (needRedraw)
                DataGridView.InvalidateCell(this);
            return childCells.Count;
        }

        public int AddChildCellRange(List<int> cellsRowIndex, bool expand = true, bool needredraw = true)
        {
            bool needRedraw = false;
            if (childCells == null)
            {
                //需要画一个加号
                childCells = new List<GroupCell>();
                needRedraw = needredraw;
                this.collapsed = !expand;
            }

            foreach (int rowindex in cellsRowIndex)
            {
                GroupCell cell = this.DataGridView.Rows[rowindex].Cells[this.ColumnIndex] as GroupCell;
                childCells.Add(cell);
                cell.groupLevel = groupLevel + 1;
                cell.parentCell = this;

                if (rowindex >= LastChild)
                {
                    LastChild = rowindex;
                }

                if (cell.ChildCells != null)
                {
                    foreach (GroupCell _cell in cell.ChildCells)
                    {
                        _cell.groupLevel = cell.groupLevel + 1;
                    }
                }
                //this.DataGridView.Rows[rowindex].Visible = expand;
            }

            if (needRedraw)
                DataGridView.InvalidateCell(this);
            return childCells.Count;
        }

        #endregion

        #region 绘制节点

        protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            if (!bPaint)
            {
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
                return;
            }

            if (this.parentCell == null && (this.childCells == null))
            {
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
                return;
            }

            Pen gridPen = new Pen(DataGridView.GridColor);

            Brush bruBK = new SolidBrush(this.Selected ? cellStyle.SelectionBackColor : cellStyle.BackColor);

            int width = PLUS_WIDTH + (groupLevel - 1) * 12;
            if (childCells == null)
                width -= 8;

            Rectangle rectLeft = new Rectangle(cellBounds.Left, cellBounds.Top - 1, width, cellBounds.Height);

            cellBounds.X += width;

            cellBounds.Width -= width;

            base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);

            PaintGroupPlus(graphics, gridPen, bruBK, cellStyle, rectLeft, collapsed);

            gridPen.Dispose();
            gridPen = null;

            bruBK.Dispose();
            bruBK = null;
        }

        private void PaintGroupPlus(Graphics graphics, Pen gridPen, Brush bruBK, DataGridViewCellStyle cellStyle, Rectangle rectLeft, bool collapsed)
        {
            Pen pen = new Pen(DataGridView.GridColor, 1);

            pen.DashStyle = DashStyle.Solid;

            graphics.FillRectangle(bruBK, rectLeft);

            int left = rectLeft.Left + (groupLevel - 1) * PLUS_WIDTH;

            //画 Left, Top, Right 三根线
            graphics.DrawLine(gridPen, left, rectLeft.Top, rectLeft.Right, rectLeft.Top);//上

            graphics.DrawLine(gridPen, rectLeft.Right, rectLeft.Bottom, rectLeft.Left, rectLeft.Bottom);

            //最左边的一条线
            graphics.DrawLine(gridPen, rectLeft.Left, rectLeft.Top, rectLeft.Right, rectLeft.Top);

            int plus = 12;

            //如果有子结点， 则需要画一个方框, 里面有+号或-号
            if (childCells != null && childCells.Count > 0)
            {
                groupPlusRect = new Rectangle(rectLeft.Left + (groupLevel - 1) * 12 + 6, rectLeft.Top + (rectLeft.Height - 12) / 2, 12, 12);

                graphics.DrawRectangle(gridPen, groupPlusRect);

                graphics.DrawLine(gridPen, groupPlusRect.Left + 3, groupPlusRect.Top + groupPlusRect.Height / 2, groupPlusRect.Right - 3, groupPlusRect.Top + groupPlusRect.Height / 2);

                if (collapsed)
                {
                    graphics.DrawLine(gridPen, groupPlusRect.Left + groupPlusRect.Width / 2, groupPlusRect.Top + 3, groupPlusRect.Left + groupPlusRect.Width / 2, groupPlusRect.Bottom - 3);
                }
                else//展开底部有一个竖线
                {
                    graphics.DrawLine(gridPen, groupPlusRect.Left + groupPlusRect.Width / 2, groupPlusRect.Top + groupPlusRect.Height, groupPlusRect.Left + groupPlusRect.Width / 2, rectLeft.Bottom);
                }

                plus = 6;
            }

            if (this.parentCell != null)
            {
                int x = rectLeft.Left + (groupLevel - 1) * 12;

                //表示是最后一个节点
                if (IsLastCell())
                {
                    graphics.DrawLine(pen, x, rectLeft.Top, x, rectLeft.Top + rectLeft.Height / 2);
                }
                else
                {
                    graphics.DrawLine(pen, x, rectLeft.Top, x, rectLeft.Bottom);
                }

                graphics.DrawLine(pen, x, rectLeft.Top + rectLeft.Height / 2, x + plus, rectLeft.Top + rectLeft.Height / 2);

                GroupCell temp = this.parentCell;

                while (temp != null)
                {
                    if (!temp.IsLastCell() && temp.groupLevel > 1)
                    {
                        x = rectLeft.Left + (temp.groupLevel - 1) * 12;

                        graphics.DrawLine(pen, x, rectLeft.Top, x, rectLeft.Bottom);
                    }
                    temp = temp.parentCell;
                }
            }

            pen.Dispose();
            pen = null;
        }

        #endregion

        #region 判断

        /// <summary>
        /// 该节点是否为某一级节点的最后一个子结点
        /// </summary>
        /// <param name="level">节点层级</param>
        /// <returns></returns>
        private bool IsLastCell(int level)
        {
            int row = DataGridView.Rows.GetNextRow(RowIndex, DataGridViewElementStates.None);
            if (row == -1)
                return true;
            GroupCell cel = DataGridView.Rows[row].Cells[0] as GroupCell;
            return (cel.GroupLevel == level);
        }

        private bool IsLastCell()
        {
            if (this.parentCell != null)
                if (this.RowIndex == this.parentCell.LastChild)
                {
                    return true;
                }

            return false;
        }

        #endregion

        #region 点击 Cell

        protected override void OnMouseDown(DataGridViewCellMouseEventArgs e)
        {
            Rectangle rect = DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, false);
            Point pt = new Point(rect.Left + e.Location.X, rect.Top + e.Location.Y);
            if (groupPlusRect.Contains(pt))
            {
                if (collapsed)
                {
                    Expand();
                }
                else
                {
                    Collapse();
                }
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseMove(DataGridViewCellMouseEventArgs e)
        {
            base.OnMouseMove(e);

            Rectangle rect = DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, false);
            Point pt = new Point(rect.Left + e.Location.X, rect.Top + e.Location.Y);
            if (groupPlusRect.Contains(pt))
            {
                InRect = true;
            }
            else
            {
                InRect = false;
            }
        }

        #endregion

        #region 展开/收起节点

        /// <summary>
        /// 展开节点
        /// </summary>
        public void Expand()
        {
            if (parentCell != null)
            {
                parentCell.CollapseAll();
            }
            collapsed = false;
            ShowChild(true);
            base.DataGridView.InvalidateCell(this);
        }

        private void ShowChild(bool show)
        {
            if (childCells == null)
                return;
            foreach (GroupCell cel in childCells)
            {
                if (cel.RowIndex == -1)
                {
                    continue;
                }

                DataGridView.Rows[cel.RowIndex].Visible = show;
                if (!cel.collapsed)
                    cel.ShowChild(show);
            }
        }

        /// <summary>
        /// 收起节点
        /// </summary>
        public void Collapse()
        {
            collapsed = true;
            ShowChild(false);
            base.DataGridView.InvalidateCell(this);
        }

        /// <summary>
        /// 展开节点及子结点
        /// </summary>
        public void ExpandAll()
        {
            if (childCells == null)
                return;
            foreach (GroupCell cel in childCells)
            {
                cel.ExpandAll();
            }
        }

        public void CollapseAll()
        {
            if (childCells == null)
                return;
            foreach (GroupCell cel in childCells)
            {
                cel.CollapseAll();
            }
        }

        #endregion
    }
}
